package cn.zyq.ykb.system.cos;



import cn.zyq.ykb.system.ry.util.StringUtils;
import com.aliyun.oss.*;
import com.aliyun.oss.common.auth.CredentialsProviderFactory;
import com.aliyun.oss.common.auth.EnvironmentVariableCredentialsProvider;
import com.aliyun.oss.internal.Mimetypes;
import com.aliyun.oss.model.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.Resource;
import org.springframework.core.io.UrlResource;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Random;
import java.util.stream.Stream;
public class AliyunCos implements cos {
	private static final Logger logger = LoggerFactory.getLogger(AliyunCos.class);

	private String endpoint;
	private String accessKeyId;
	private String accessKeySecret;
	private String bucketName;
	private String roleArn;
	private String roleSessionName;
//	private String FOLDER=OSSProperties.ALIYUN_DIR;
	@Autowired
	private  LocalCos localCos;
	public String getEndpoint() {
		return endpoint;
	}

	public void setEndpoint(String endpoint) {
		this.endpoint = endpoint;
	}

	public String getAccessKeyId() {
		return accessKeyId;
	}

	public void setAccessKeyId(String accessKeyId) {
		this.accessKeyId = accessKeyId;
	}

	public String getAccessKeySecret() {
		return accessKeySecret;
	}

	public void setAccessKeySecret(String accessKeySecret) {
		this.accessKeySecret = accessKeySecret;
	}

	public String getBucketName() {
		return bucketName;
	}

	public void setBucketName(String bucketName) {
		this.bucketName = bucketName;
	}

	public String getRoleArn() {
		return roleArn;
	}

	public void setRoleArn(String roleArn) {
		this.roleArn = roleArn;
	}

	public String getRoleSessionName() {
		return roleSessionName;
	}

	public void setRoleSessionName(String roleSessionName) {
		this.roleSessionName = roleSessionName;
	}
	/**
	 * 获取阿里云OSS客户端对象
	 *
	 * @return ossClient
	 */
	private OSSClient getOSSClient() {
		return new OSSClient(endpoint, accessKeyId, accessKeySecret);
	}

	private String getBaseUrl() {
//		return "https://" + bucketName + "." + endpoint + "/";
		return endpoint;
	}

	/**
	 * 阿里云OSS对象存储简单上传实现
	 */
	@Override
	public void store(InputStream inputStream, long contentLength, String contentType, String keyName) {
		try {
			logger.info("阿里云存储OSS对象 内容长度：{},文件类型：{},KeyName:{}",contentLength,contentType,keyName);
			// 简单文件上传, 最大支持 5 GB, 适用于小文件上传, 建议 20M以下的文件使用该接口
			ObjectMetadata objectMetadata = new ObjectMetadata();
			objectMetadata.setContentLength(contentLength);
//			objectMetadata.setContentType("image/jpg");
			objectMetadata.setContentType(getcontentType(keyName.substring(keyName.lastIndexOf("."))));
			// 对象键（Key）是对象在存储桶中的唯一标识。
			PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName, keyName, inputStream, objectMetadata);
			PutObjectResult putObjectResult = getOSSClient().putObject(putObjectRequest);
			if (putObjectResult != null && putObjectResult.getResponse() != null) {
				logger.info("阿里云存储结果code：" + putObjectResult.getResponse().getStatusCode());
			}
		} catch (Exception ex) {
			logger.error("阿里云存储 keyName：{} ,失败：{}",keyName,ex.getMessage());
			ex.printStackTrace();
		}

	}
//	public static void main(String[] args) throws Exception {
//		// Endpoint以华东1（杭州）为例，其它Region请按实际情况填写。
////		String endpoint = "https://oss-cn-hangzhou.aliyuncs.com";
//		// 从环境变量中获取访问凭证。运行本代码示例之前，请确保已设置环境变量OSS_ACCESS_KEY_ID和OSS_ACCESS_KEY_SECRET。
//		EnvironmentVariableCredentialsProvider credentialsProvider = CredentialsProviderFactory.newEnvironmentVariableCredentialsProvider();
//		// 填写Bucket名称，例如examplebucket。
////		String bucketName = "examplebucket";
//		// 填写Object完整路径，例如exampledir/exampleobject.txt。Object完整路径中不能包含Bucket名称。
////		String objectName = "exampledir/exampleobject.txt";
//		// 待上传本地文件路径。
//		String filePath = "D:\\localpath\\examplefile.txt";
//
//		// 创建OSSClient实例。
//		OSS ossClient = new OSSClientBuilder().build(endpoint, credentialsProvider);
//		try {
//			// 创建InitiateMultipartUploadRequest对象。
//			InitiateMultipartUploadRequest request = new InitiateMultipartUploadRequest(bucketName, objectName);
//			// 如果需要在初始化分片时设置请求头，请参考以下示例代码。
//			ObjectMetadata metadata = new ObjectMetadata();
//			// 根据文件自动设置ContentType。如果不设置，ContentType默认值为application/oct-srream。
//			if (metadata.getContentType() == null) {
//				metadata.setContentType(Mimetypes.getInstance().getMimetype(new File(filePath), objectName));
//			}
//
//			// 初始化分片。
//			InitiateMultipartUploadResult upresult = ossClient.initiateMultipartUpload(request);
//			// 返回uploadId。
//			String uploadId = upresult.getUploadId();
//			// partETags是PartETag的集合。PartETag由分片的ETag和分片号组成。
//			List<PartETag> partETags =  new ArrayList<PartETag>();
//			// 每个分片的大小，用于计算文件有多少个分片。单位为字节。
//			final long partSize = 1 * 1024 * 1024L;   //1 MB。
//
//			// 根据上传的数据大小计算分片数。以本地文件为例，说明如何通过File.length()获取上传数据的大小。
//			final File sampleFile = new File(filePath);
//			long fileLength = sampleFile.length();
//			int partCount = (int) (fileLength / partSize);
//			if (fileLength % partSize != 0) {
//				partCount++;
//			}
//			// 遍历分片上传。
//			for (int i = 0; i < partCount; i++) {
//				long startPos = i * partSize;
//				long curPartSize = (i + 1 == partCount) ? (fileLength - startPos) : partSize;
//				UploadPartRequest uploadPartRequest = new UploadPartRequest();
//				uploadPartRequest.setBucketName(bucketName);
//				uploadPartRequest.setKey(objectName);
//				uploadPartRequest.setUploadId(uploadId);
//				// 设置上传的分片流。
//				// 以本地文件为例说明如何创建FIleInputstream，并通过InputStream.skip()方法跳过指定数据。
//				InputStream instream = new FileInputStream(sampleFile);
//				instream.skip(startPos);
//				uploadPartRequest.setInputStream(instream);
//				// 设置分片大小。除了最后一个分片没有大小限制，其他的分片最小为100 KB。
//				uploadPartRequest.setPartSize(curPartSize);
//				// 设置分片号。每一个上传的分片都有一个分片号，取值范围是1~10000，如果超出此范围，OSS将返回InvalidArgument错误码。
//				uploadPartRequest.setPartNumber( i + 1);
//				// 每个分片不需要按顺序上传，甚至可以在不同客户端上传，OSS会按照分片号排序组成完整的文件。
//				UploadPartResult uploadPartResult = ossClient.uploadPart(uploadPartRequest);
//				// 每次上传分片之后，OSS的返回结果包含PartETag。PartETag将被保存在partETags中。
//				partETags.add(uploadPartResult.getPartETag());
//			}
//
//
//			// 创建CompleteMultipartUploadRequest对象。
//			// 在执行完成分片上传操作时，需要提供所有有效的partETags。OSS收到提交的partETags后，会逐一验证每个分片的有效性。当所有的数据分片验证通过后，OSS将把这些分片组合成一个完整的文件。
//			CompleteMultipartUploadRequest completeMultipartUploadRequest =
//					new CompleteMultipartUploadRequest(bucketName, objectName, uploadId, partETags);
//			// 完成分片上传。
//			CompleteMultipartUploadResult completeMultipartUploadResult = ossClient.completeMultipartUpload(completeMultipartUploadRequest);
//			System.out.println(completeMultipartUploadResult.getETag());
//		} catch (OSSException oe) {
//			System.out.println("Caught an OSSException, which means your request made it to OSS, "
//					+ "but was rejected with an error response for some reason.");
//			System.out.println("Error Message:" + oe.getErrorMessage());
//			System.out.println("Error Code:" + oe.getErrorCode());
//			System.out.println("Request ID:" + oe.getRequestId());
//			System.out.println("Host ID:" + oe.getHostId());
//		} catch (ClientException ce) {
//			System.out.println("Caught an ClientException, which means the client encountered "
//					+ "a serious internal problem while trying to communicate with OSS, "
//					+ "such as not being able to access the network.");
//			System.out.println("Error Message:" + ce.getMessage());
//		} finally {
//			if (ossClient != null) {
//				ossClient.shutdown();
//			}
//		}
//}




	//通过该方法快速获取文件类型
	public static String getcontentType(String FilenameExtension) {
		if (FilenameExtension.equalsIgnoreCase(".bmp")) {
			return "image/bmp";
		}
		if (FilenameExtension.equalsIgnoreCase(".gif")) {
			return "image/gif";
		}
		if (FilenameExtension.equalsIgnoreCase(".jpeg") ||
				FilenameExtension.equalsIgnoreCase(".jpg") ||
				FilenameExtension.equalsIgnoreCase(".png")) {
			return "image/jpg";
		}
		if (FilenameExtension.equalsIgnoreCase(".html")) {
			return "text/html";
		}
		if (FilenameExtension.equalsIgnoreCase(".txt")) {
			return "text/plain";
		}
		if (FilenameExtension.equalsIgnoreCase(".vsd")) {
			return "application/vnd.visio";
		}
		if (FilenameExtension.equalsIgnoreCase(".pptx") ||
				FilenameExtension.equalsIgnoreCase(".ppt")) {
			return "application/vnd.ms-powerpoint";
		}
		if (FilenameExtension.equalsIgnoreCase(".docx") ||
				FilenameExtension.equalsIgnoreCase(".doc")) {
			return "application/msword";
		}
		if (FilenameExtension.equalsIgnoreCase(".xml")) {
			return "text/xml";
		}
		return "image/jpg";
	}


	@Override
	public Stream<Path> loadAll() {
		return null;
	}

	@Override
	public Path load(String keyName) {
		Path rootLocation = Paths.get(localCos.getStoragePath());
		try {
			Files.createDirectories(rootLocation);
		} catch (IOException e) {
			e.printStackTrace();
		}
		return rootLocation.resolve(keyName);
	}

	@Override
	public Resource loadAsResource(String keyName) {
		try {
			Path file = load(keyName);
			Resource resource = new UrlResource(file.toUri());
			if (resource.exists() || resource.isReadable()) {
				return resource;
			} else {
				return null;
			}
		} catch (MalformedURLException e) {
			e.printStackTrace();
			return null;
		}
	}

	@Override
	public void delete(String keyName) {
		try {
			getOSSClient().deleteObject(bucketName, keyName);
		} catch (Exception e) {
			e.printStackTrace();
		}

	}

	@Override
	public String generateUrl(String keyName) {
		return getBaseUrl() + keyName;
	}
}
